/*
 *    Copyright (c) 2018-2025, boss All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the boss developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: boss
 */
package com.hopes.bizz.risk.control.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hopes.bizz.common.core.util.DateUtils;
import com.hopes.bizz.common.core.util.StringUtils;
import com.hopes.bizz.risk.common.constant.HidDicConstant;
import com.hopes.bizz.risk.common.constant.RiskDicConstant;
import com.hopes.bizz.risk.common.constant.enums.RiskHidSourceEnum;
import com.hopes.bizz.risk.common.constant.enums.RiskSysDictEnum;
import com.hopes.bizz.risk.control.dto.RiskMeasureTaskDTO;
import com.hopes.bizz.risk.control.entity.RiskMeasureTaskConfigEntity;
import com.hopes.bizz.risk.control.entity.RiskMeasureTaskEntity;
import com.hopes.bizz.risk.control.entity.RiskObjectEntity;
import com.hopes.bizz.risk.control.mapper.RiskMeasureTaskMapper;
import com.hopes.bizz.risk.control.service.RiskMeasureTaskService;
import com.hopes.bizz.risk.control.service.RiskObjectService;
import com.hopes.bizz.risk.control.vo.RiskMeasureTaskVO;
import com.hopes.bizz.risk.control.vo.RiskObjectVO;
import com.hopes.bizz.risk.hid.bo.RiskHidHiddenDangerBO;
import com.hopes.bizz.risk.hid.service.RiskHidHiddenDangerService;
import com.hopes.bizz.risk.statistic.bo.SafetyStatisticsBO;
import com.hopes.bizz.risk.statistic.dto.SafetyStatisticsDTO;
import com.hopes.boss.admin.api.entity.SysDictItem;
import com.hopes.boss.admin.api.resolver.DictResolver;
import com.hopes.boss.common.core.constant.CommonConstants;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 隐患排查任务设置
 *
 * @author pig
 * @date 2023-07-20 09:01:45
 */
@Service
@RequiredArgsConstructor
public class RiskMeasureTaskServiceImpl extends ServiceImpl<RiskMeasureTaskMapper, RiskMeasureTaskEntity> implements RiskMeasureTaskService {

    private final RiskObjectService riskObjectService;

    //隐患排查任务设置Mapper
    private final RiskMeasureTaskMapper riskMeasureTaskMapper;

    private final RiskHidHiddenDangerService hidHiddenDangerService;
    @Override
    public Page<RiskMeasureTaskVO> listPage(Page<RiskMeasureTaskVO> page, RiskMeasureTaskDTO riskMeasureTaskDTO) {
        riskMeasureTaskDTO.setDelFlag(CommonConstants.STATUS_NORMAL);
        Page<RiskMeasureTaskVO> riskMeasureTaskVOPage = this.baseMapper.listPage(page, riskMeasureTaskDTO);
        Map<Long, List<RiskMeasureTaskVO>> map = riskMeasureTaskVOPage.getRecords().stream()
                .collect(Collectors.groupingBy(RiskMeasureTaskVO::getRiskTaskConfigId));
        map.forEach((k,v)->{
            v.get(0).setRowCount(v.size());
        });
        Map<Long, List<RiskMeasureTaskVO>> eventMap = riskMeasureTaskVOPage.getRecords().stream()
                .collect(Collectors.groupingBy(RiskMeasureTaskVO::getRiskEventId));
        eventMap.forEach((k,v)->{
            v.get(0).setRiskEventRowCount(v.size());
        });
        return riskMeasureTaskVOPage;
    }


    @Override
    public boolean removeBatchByIds(Collection<?> list) {
        if (CollUtil.isEmpty(list)) {
            return true;
        }
        stopTask(list);
        return baseMapper.deleteBatchIds(list) > 0;
    }

    @Override
    public void batchSaveWithTaskConfig(RiskMeasureTaskConfigEntity measureTaskConfigEntity, List<RiskMeasureTaskEntity> riskMeasureTaskList) {
        if (CollectionUtil.isEmpty(riskMeasureTaskList)) {
            return;
        }
        riskMeasureTaskList.forEach(item -> {
            item.setRiskTaskConfigId(measureTaskConfigEntity.getId());
            item.setRiskUnitId(measureTaskConfigEntity.getRiskUnitId());
            item.setRiskEventId(measureTaskConfigEntity.getRiskEventId());
            item.setCheckContent(measureTaskConfigEntity.getCheckContent());
            item.setRiskControlId(measureTaskConfigEntity.getRiskControlId());
            item.setTaskStatus(RiskDicConstant.HIDDEN_CHECK_CONFIG_STATUS_NOT_USE);
        });
        this.saveBatch(riskMeasureTaskList);
    }

    @Override
    public boolean startTask(Collection<?> list) {
        final List<RiskMeasureTaskEntity> measureTaskList = getRiskMeasureTaskEntityList(list);
        if (measureTaskList == null) return false;
        // 当前日期
        final Calendar instance = Calendar.getInstance();
        final String nowDayStr = DateUtils.limitDay(instance.getTime());
        measureTaskList.forEach(item -> {
            final Date workStartTime = DateUtils.parseDate(nowDayStr + " " + item.getWorkStartTime(), DateUtils.FORMAT_SECOND);
            item.setStartCheckDate(workStartTime);
            item.setTaskStatus(RiskDicConstant.HIDDEN_CHECK_CONFIG_STATUS_USE);
        });
        return updateBatchById(measureTaskList);
    }

    @Override
    public boolean stopTask(Collection<?> list) {
        final List<RiskMeasureTaskEntity> measureTaskList = getRiskMeasureTaskEntityList(list);
        if (measureTaskList == null) return false;
        measureTaskList.forEach(item -> {
            item.setLatestCheckDate(null);
            item.setTaskStatus(RiskDicConstant.HIDDEN_CHECK_CONFIG_STATUS_NOT_USE);
        });
        return updateBatchById(measureTaskList);
    }

    @Override
    public Page<RiskObjectVO> taskStatistics(Page page, SafetyStatisticsDTO safetyStatisticsDto) {
        LambdaQueryWrapper<RiskObjectEntity> wrapper = Wrappers.lambdaQuery();

        List<SysDictItem> workTypeList = DictResolver.getItemsByType(RiskSysDictEnum.risk_work_type);
        wrapper.eq(StringUtils.isNotBlank(safetyStatisticsDto.getDeptId()), RiskObjectEntity::getDeptId, safetyStatisticsDto.getDeptId());
        wrapper.eq(StringUtils.isNotBlank(safetyStatisticsDto.getHazardType()), RiskObjectEntity::getHazardType, safetyStatisticsDto.getHazardType());
        wrapper.eq(RiskObjectEntity::getHazardSourceFlag, Boolean.TRUE);
        Page<RiskObjectVO> riskObjectPageInfo = riskObjectService.page(page, wrapper);
        List<RiskObjectVO> voList = new ArrayList<>();
        for (Object record : riskObjectPageInfo.getRecords()) {
            RiskObjectVO vo = new RiskObjectVO();
            BeanUtils.copyProperties(record, vo);
            voList.add(vo);
        }
        riskObjectPageInfo.setRecords(voList);

        for (RiskObjectVO riskObject : riskObjectPageInfo.getRecords()) {
            SafetyStatisticsDTO entity = new SafetyStatisticsDTO();
            BeanUtils.copyProperties(safetyStatisticsDto, entity);
            entity.setId(riskObject.getId());
            // 获取当前对象的任务信息根据workType和status分组统计个数
            Map<String, Map<String, Integer>> map = riskMeasureTaskMapper.getTaskCountByStatusType(entity)
                    .stream()
                    .filter(item -> item.getTaskStatus() != null && item.getWorkType() != null)
                    .collect(Collectors.groupingBy(SafetyStatisticsBO::getWorkType,
                            Collectors.groupingBy(SafetyStatisticsBO::getTaskStatus,
                                    Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0).getCount()))));
            JSONObject jsonObject = new JSONObject();
            double totalFinish = 0.0;
            long totalSum = 0L;

            for (SysDictItem labelValue : workTypeList) {
                String workType = labelValue.getCode();
                // 不包括日常任务
                if (RiskDicConstant.RISK_WORK_TYPE_0.toString().equals(workType)) {
                    continue;
                }
                Map<String, Integer> statusCount = map.get(workType);
                double finish = 0.0; // 完成个数
                long sum = 0L; //总数
                if (statusCount != null) {
                    // 获取总数和完成的数量，计算百分比
                    for (String s : statusCount.keySet()) {
                        // 完成状态
                        if (s.equals(RiskDicConstant.HIDDEN_CHECK_TASK_STATUS_FINISH.toString())) {
                            finish += statusCount.get(s);
                            totalFinish += statusCount.get(s);
                        }
                        sum += statusCount.get(s);
                        totalSum += statusCount.get(s);
                    }
                }
                // 计算百分比
                double percent = 0.0;
                if (sum != 0L) {
                    percent = NumberUtil.round((finish / sum) * 100,2).doubleValue();
                }
                JSONObject value = new JSONObject();
                value.put("finish", finish);
                value.put("percent", percent);
                jsonObject.put(labelValue.getExt1(), value);
            }
            // 计算百分比
            double percent = 0.0;
            if (totalSum != 0L) {
                percent = NumberUtil.round((totalFinish / totalSum) * 100,2).doubleValue();
            }
            JSONObject value = new JSONObject();
            value.put("finish", totalFinish);
            value.put("percent", percent);
            jsonObject.put("total", value);

            // 获取风险分级管控的隐患任务数
            RiskHidHiddenDangerBO danger = new RiskHidHiddenDangerBO();
            BeanUtils.copyProperties(safetyStatisticsDto, danger);
            danger.setBizCode(RiskHidSourceEnum.RISK_CONTROL.getCode());
            danger.setId(riskObject.getId());
            List<Integer> dangerList = hidHiddenDangerService.getSafetyHidData(danger);
            Map<Boolean, Long> hidStatus = dangerList.stream()
                    .collect(Collectors.groupingBy(item -> HidDicConstant.HID_DANGER_STATUS_WAIT_ACCEPTANCE <= item, Collectors.counting()));
            JSONObject hid = new JSONObject();
            Long finish = hidStatus.get(Boolean.TRUE);
            Long unFinish = hidStatus.get(Boolean.FALSE);
            hid.put("total", (finish == null ? 0 : finish) + (unFinish == null ? 0 : unFinish));
            hid.put("finish", finish == null ? 0 : finish);
            jsonObject.put("hid", hid);
            riskObject.setSafetyStatistics(jsonObject);
        }
        return riskObjectPageInfo;
    }

    @Override
    public List<RiskMeasureTaskEntity> getByRiskUnitIdList(List<Long> riskUnitIdList) {
        if (CollectionUtil.isEmpty(riskUnitIdList)) {
            return new ArrayList<>();
        }
        return riskMeasureTaskMapper.queryListByRiskUnitIdList(riskUnitIdList);
    }

    @Nullable
    private List<RiskMeasureTaskEntity> getRiskMeasureTaskEntityList(Collection<?> list) {
        if (CollUtil.isEmpty(list)) {
            return null;
        }
        /* 查询任务 */
        return this.list(Wrappers.<RiskMeasureTaskEntity>lambdaQuery().in(RiskMeasureTaskEntity::getId, list));
    }
}
